﻿using System;
using System.Collections.Generic;
using System.Data.Objects;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;
using System.Web;
using System.Web.Security;
using Tebbee.Business.Server.Common.Email;
using Tebbee.Business.Server.Model;

namespace Tebbee.Business.Server
{
    // NOTE: You can use the "Rename" command on the "Refactor" menu to change the class name "AccountSer" in code, svc and config file together.
    // NOTE: In order to launch WCF Test Client for testing this service, please select AccountSer.svc or AccountSer.svc.cs at the Solution Explorer and start debugging.
    public class AccountSer : IAccountSer
    {
        private readonly TebbeeContext context;

        public AccountSer()
        {
            context = new TebbeeContext();
        }


        public int ResetPassword(string userName)
        {
            MembershipUser user = Membership.GetUser(userName);

            if (user.ChangePassword(user.ResetPassword(), "123456"))
            {
                return 1;
            }
            else
            {
                return 0;
            }
        }

        public int PublisherRegPackage(int pubId, DateTime availableDate, DateTime expriedDate)
        {
            ObjectParameter rowEffect = new ObjectParameter("RowEffected", typeof(Int32));
            context.Publisher_RegPackage(pubId, availableDate, expriedDate, rowEffect);

            int rs = (Int32)rowEffect.Value;

            return rs;
        }

        public int RemoveSubcribe(int subId)
        {
            ObjectParameter rowEffect = new ObjectParameter("RowEffected", typeof(Int32));
            context.Member_RemoveSubcribe(subId, rowEffect);
            return (Int32)rowEffect.Value;
        }
        public ICollection<Member_SubcribeList_Result> GetSubcribeList(string userName, int currentPage, out int totalPage)
        {
            ObjectParameter ttPage = new ObjectParameter("TotalPage", typeof(Int32));
            var tmp = context.Member_SubcribeList(userName, currentPage, ttPage).ToList();
            totalPage = (Int32)ttPage.Value;

            return tmp;
        }

        public Member_ChangeAvatar_Result ChangeAvatar(string userName, string type)
        {
            return context.Member_ChangeAvatar(userName, type).Single();
        }
        private string GetErrorMessage(MembershipCreateStatus status)
        {
            switch (status)
            {
                case MembershipCreateStatus.DuplicateUserName:
                    return "Tài Khoản Này Đã Tồn Tại. Xin Hãy Dùng Tài Khoản Khác.";

                case MembershipCreateStatus.DuplicateEmail:
                    return "Email Này Đã Tồn Tại. Xin Hãy Dùng Email Khác.";

                case MembershipCreateStatus.InvalidPassword:
                    return "Mật Khẩu Không Hợp Lệ. Xin Hãy Dùng Mật Khẩu Khác.";

                case MembershipCreateStatus.InvalidEmail:
                    return "Email Không Hợp Lệ. Xin Kiểm Tra Lại Cho Chính Xác.";

                case MembershipCreateStatus.InvalidAnswer:
                    return "The password retrieval answer provided is invalid. Please check the value and try again.";

                case MembershipCreateStatus.InvalidQuestion:
                    return "The password retrieval question provided is invalid. Please check the value and try again.";

                case MembershipCreateStatus.InvalidUserName:
                    return "Tài Khoản Không Hợp Lệ. Xin Kiểm Tra Lại Cho Chính Xác.";

                case MembershipCreateStatus.ProviderError:
                    return "The authentication provider returned an error. Please verify your entry and try again. If the problem persists, please contact your system administrator.";

                case MembershipCreateStatus.UserRejected:
                    return "The user creation request has been canceled. Please verify your entry and try again. If the problem persists, please contact your system administrator.";

                default:
                    return "An unknown error occurred. Please verify your entry and try again. If the problem persists, please contact your system administrator.";
            }
        }

        //public ICollection<Member_ExchangeLog_Result> GetExchangeLog(string userName, int currentPage, out int totalPage)
        //{
        //    ObjectParameter ttPage = new ObjectParameter("TotalPage", typeof(Int32));
        //    var tmp = context.Member_ExchangeLog(userName, currentPage, ttPage).ToList();
        //    totalPage = (Int32)ttPage.Value;

        //    return tmp;
        //}

        public ICollection<Member_PointList_Result> GetPointList(string userName, int currentPage, out int totalPage)
        {
            ObjectParameter ttPage = new ObjectParameter("TotalPage", typeof(Int32));
            var tmp = context.Member_PointList(userName, currentPage, ttPage).ToList();
            totalPage = (Int32)ttPage.Value;

            return tmp;
        }

        public Member_GetByUserName_Result GetMemberByUserName(string userName)
        {
            return context.Member_GetByUserName(userName).Single();
        }

        public Member_GetByMemId_Result GetMemberById(int memId)
        {
            return context.Member_GetByMemId(memId).Single();
        }
        public ICollection<Member_All_Result> AllMembers()
        {
            return context.Member_All().ToList();
        }

        public ICollection<Member_List_Result> ListMembers(int startRow, string searchString)
        {
            return context.Member_List(startRow, searchString).ToList();
        }
  
        public int AddNewMember(MemberFull mem, out string msg)
        {
            try
            {
                MembershipUser user = Membership.CreateUser(
                      mem.UserName,
                      mem.Password,
                      mem.Email);

                Guid userId = (Guid)user.ProviderUserKey;

                Roles.AddUserToRole(mem.UserName, "Member");

                ObjectParameter ReturnId = new ObjectParameter("ReturnId", typeof(Int32));
                context.Member_Add(userId, mem.FirstName, mem.LastName, mem.Gender, ReturnId);
                msg = "Create New Member Sucessfull !!!";
                return (Int32)ReturnId.Value;
            }
            catch (MembershipCreateUserException ex)
            {
                msg = GetErrorMessage(ex.StatusCode);
            }
            catch (HttpException ex)
            {
                msg = ex.Message;
            }

            return 0;
        }

        public int EditProfilesMember(MemberFull mem, out string msg)
        {
            //true if don't exist >> must update, false >> must continue check
            bool emailOK = Membership.GetUserNameByEmail(mem.Email) == null;

            if (emailOK)
            {
                MembershipUser user = Membership.GetUser(mem.UserName);
                user.Email = mem.Email;
                Membership.UpdateUser(user);
            }
            else
            {
                //true >> don't need update, false >> error
                emailOK = Membership.GetUserNameByEmail(mem.Email).Equals(mem.UserName);
            }

            if (emailOK)
            {
                ObjectParameter rowEffect = new ObjectParameter("RowEffected", typeof(Int32));
                context.Member_Edit(mem.MemId, mem.FirstName, mem.LastName, mem.Gender, mem.CMND, rowEffect);

                int rs = (Int32)rowEffect.Value;
                msg = rs == 0 ? "Tài khoản này không tồn tại hoặc đã bị xóa trước đó. Hãy f5 lại để cập nhật thông tin chính xác hiện tại." : "";
                return rs;
            }
            else
            {
                msg = "Email đã tồn tại trong hệ thống. Xin sử dụng email cũ hoặc đổi email khác và thử lại.";
                return 0;
            }  
        }

        public int EditFullProfilesMember(MemberFull mem, out string msg)
        {
            //true if don't exist >> must update, false >> must continue check
            bool emailOK = Membership.GetUserNameByEmail(mem.Email) == null;

            if (emailOK)
            {
                MembershipUser user = Membership.GetUser(mem.UserName);
                user.Email = mem.Email;
                Membership.UpdateUser(user);
            }
            else
            {
                //true >> don't need update, false >> error
                emailOK = Membership.GetUserNameByEmail(mem.Email).Equals(mem.UserName);
            }

            if (emailOK)
            {
                ObjectParameter rowEffect = new ObjectParameter("RowEffected", typeof(Int32));
                context.Member_EditFull(mem.UserName, mem.FirstName, mem.LastName, mem.Gender, mem.Birthday, mem.CMND,
                mem.Address, mem.Phone, rowEffect);

                int rs = (Int32)rowEffect.Value;
                if (rs == 0)
                {
                    rs = -1;
                    msg = "Tài khoản này không tồn tại hoặc bị xóa bởi người quản trị. Xin hãy liên hệ với quản trị và đăng nhập lại vào hệ thống";
                }
                else
                {
                    msg = "";
                }
                return rs;
            }
            else
            {
                msg = "Email đã tồn tại trong hệ thống. Xin sử dụng email cũ hoặc đổi email khác và thử lại.";
                return 0;
            }
        }

        public int DeleteMember(int memId)
        {
            ObjectParameter rowEffect = new ObjectParameter("RowEffected", typeof(Int32));
            ObjectParameter userName = new ObjectParameter("userName", typeof(string));
            context.Member_Delete(memId, userName, rowEffect);

            string user = (string) userName.Value;

            Roles.RemoveUserFromRole(user, "Member");
            Membership.DeleteUser(user, true);
            return (Int32)rowEffect.Value;
        }

        public ICollection<Publisher_All_Result> AllPublishers()
        {
            var returnPub = context.Publisher_All().ToList();

            return returnPub;
        }

        public ICollection<Publisher_List_Result> ListPublishers(int startRow, string searchString)
        {

            var returnPub = context.Publisher_List(startRow, searchString).ToList();

            return returnPub;
        }

        public int AddNewPublisher(PublisherFull pub, out string msg)
        {
            try
            {
                MembershipUser user = Membership.CreateUser(
                      pub.UserName,
                      pub.Password,
                      pub.Email);

                Guid userId = (Guid)user.ProviderUserKey;

                Roles.AddUserToRole(pub.UserName, "Publisher");

                ObjectParameter ReturnId = new ObjectParameter("ReturnId", typeof(Int32));
                context.Publisher_Add(userId, pub.AvailableDate, pub.ExpriedDate, pub.CompanyName, pub.CompanyDes, ReturnId);

                msg = "Create New Publisher Sucessfull !!!";
                return (Int32)ReturnId.Value;
            }
            catch (MembershipCreateUserException ex)
            {
                msg = GetErrorMessage(ex.StatusCode);
            }
            catch (HttpException ex)
            {
                msg = ex.Message;
            }

            return 0;
        }

        public int EditProfilesPublisher(PublisherFull pub, out string msg)
        {
            //true if don't exist >> must update, false >> must continue check
            bool emailOK = Membership.GetUserNameByEmail(pub.Email) == null;

            if (emailOK)
            {
                MembershipUser user = Membership.GetUser(pub.UserName);
                user.Email = pub.Email;
                Membership.UpdateUser(user);   
            }
            else
            {
                //true >> don't need update, false >> error
                emailOK = Membership.GetUserNameByEmail(pub.Email).Equals(pub.UserName);
            }

            if (emailOK)
            {
                ObjectParameter rowEffect = new ObjectParameter("RowEffected", typeof(Int32));
                context.Publisher_Edit(pub.PubId, pub.AvailableDate, pub.ExpriedDate, pub.CompanyName,
                    pub.CompanyDes, pub.CMND, pub.LogoLink, pub.Facebook, rowEffect);

                int rs = (Int32)rowEffect.Value;
                msg = rs == 0 ? "That account may be deleted before. Please f5 to update correct information." : "";
                return rs;
            }
            else
            {
                msg = "The e-mail address that you entered is already in use. Please enter a different or keep old e-mail address.";
                return 0;
            }     
        }

        public int DeletePublisher(int pubId)
        {
            ObjectParameter rowEffect = new ObjectParameter("RowEffected", typeof(Int32));
            ObjectParameter userName = new ObjectParameter("userName", typeof(string));
            context.Publisher_Delete(pubId, userName, rowEffect);

            string user = (string) userName.Value;

            Roles.RemoveUserFromRole(user, "Publisher");
            Membership.DeleteUser(user, true);
            
            return (Int32)rowEffect.Value;
        }

        public ICollection<Admin_ALL_Result> AllAdmin()
        {
            return context.Admin_ALL().ToList();
        }

        public ICollection<Admin_List_Result> ListAdmin(int startRow, string searchString)
        {

            return context.Admin_List(startRow, searchString).ToList();
        }

        public int AddNewAdmin(AdminFull admin, out string msg)
        {
            try
            {
                MembershipUser user = Membership.CreateUser(
                      admin.UserName,
                      admin.Password,
                      admin.Email);

                Guid userId = (Guid)user.ProviderUserKey;
                //Roles.CreateRole("Admin");
                Roles.AddUserToRole(admin.UserName, "Admin");

                ObjectParameter ReturnId = new ObjectParameter("ReturnId", typeof(Int32));
                //context.Member_Add(userId, mem.FirstName, mem.LastName, mem.Gender, ReturnId);
                context.Admin_Add(userId, admin.ImgUrl, ReturnId);
                msg = "Create New Admin Sucessfull !!!";
                return (Int32)ReturnId.Value;
            }
            catch (MembershipCreateUserException ex)
            {
                msg = GetErrorMessage(ex.StatusCode);
            }
            catch (HttpException ex)
            {
                msg = ex.Message;
            }

            return 0;
        }


        public int DeleteAdmin(int adId)
        {
            ObjectParameter rowEffect = new ObjectParameter("RowEffected", typeof(Int32));
            ObjectParameter userName = new ObjectParameter("userName", typeof(string));
            //context.Member_Delete(memId, userName, rowEffect);
            context.Admin_Delete(adId, userName, rowEffect);

            string user = (string) userName.Value;

            Roles.RemoveUserFromRole(user, "Admin");
            Membership.DeleteUser(user, true);
            return (Int32)rowEffect.Value;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="uid"></param>
        /// <param name="pwd"></param>
        /// <param name="msg"></param>
        /// <returns></returns>
        public bool Login(string uid, string pwd, out string msg)
        {
            msg = "";
            try
            {
                if (Membership.ValidateUser(uid, pwd))
                {
                    var roles = Roles.Provider.GetRolesForUser(uid);
                    msg = roles[0];
                    return true;
                }
                else
                {
                    return false;
                }
            }
            catch (Exception ex)
            {
                return false;
            }
        }

        /// <summary>
        /// Change password
        /// </summary>
        /// <param name="user"></param>
        /// <param name="msg"></param>
        /// <returns></returns>
        public bool ChangePwd(ChangePassModel user, out string msg)
        {
            try
            {
                MembershipUser u = Membership.GetUser(user.UserName);
                if (u.ChangePassword(user.OldPassword, user.NewPassword))
                {
                    msg = "Đổi Mật Khẩu Thành Công";
                    return true;
                }
                else
                {
                    msg = "Đổi Mật Khẩu Thất Bại";
                    return false;
                }
            }
            catch (Exception e)
            {
                msg = "Đổi Mật Khẩu Thất Bại";
                return false;
            }
        }
    }
}
